package DEEPERsource.DEEPERsource.source.client;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import auc.AUCCalculator;

import net.sf.javaml.classification.evaluation.PerformanceMeasure;

import preprocessing.DefaultPreprocessor;
import preprocessing.SimplePreprocessor;
import util.PPIMapping;
import util.PropertyManager;
import corpus.Text;
import corpus.ppi.CorpusFactory;

import machinelearning.SVM;
import machinelearning.evaluation.EvaluationProcedure;
import machinelearning.features.DepFeatureBuilder;
import machinelearning.features.FeatureBuilder;
import machinelearning.kernel.CompositionKernel;
import machinelearning.kernel.Kernel;
import machinelearning.kernel.SyntacticKernel;
import machinelearning.utils.ClassificationResult;
import machinelearning.utils.EvaluationEntry;
import machinelearning.utils.PrecomputedKernel;
import machinelearning.wekawrapper.Dataset;
import deeper.Direction;
import deeper.Interaction;
import deeper.InteractionType;
import edu.uci.ics.jung.graph.Edge;
import graph.Keys;

public class _Runners {
	private static Log _log = LogFactory.getLog(Runners.class);

	private PropertyManager pm;

	public _Runners(String props) {
		pm = new PropertyManager();
		pm.readParam(props);
	}

	public void setProps(String props) {
		pm = new PropertyManager();
		pm.readParam(props);
	}

	public void SVMRunner4LLL(boolean recalcKernel) {
		CorpusFactory cFactory = new CorpusFactory();
		Text lll = cFactory.getCorpusFromPPIXML("resource/lll.xml", new SimplePreprocessor());
		lll.parse(null, "serialized", "resource/sparse/lll");

		Text llltest = cFactory.getCorpusFromPPIXML("resource/llltest.xml", new SimplePreprocessor());
		llltest.parse(null, "serialized", "resource/sparse/llltest");

		Collection<Interaction> train = lll.interactions();
		Collection<Interaction> test = llltest.interactions();
		PrecomputedKernel kernel = new PrecomputedKernel(train, test, new CompositionKernel());
		if (recalcKernel) {
			kernel.calculateTrainingMatrix();
			kernel.calculateTestMatrix();
			PrintWriter writer = null;
			try {
				writer = new PrintWriter("resource/kernels/lllcomp/lllTrainKernel");
				kernel.printTrain(writer);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				writer.close();
			}
			try {
				writer = new PrintWriter("resource/kernels/lllcomp/lllTestKernel");
				kernel.printTest(writer);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				writer.close();
			}
		}
		SVM svm = new SVM();
		try {
			// "-C", "10", "-W0", "10", "-W1", "1"
			svm.setOptions(new String[] { "-K", "4", "-B", "1" });
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		Dataset trainData = new Dataset("resource/kernels/lllcomp/lllTrainKernel");
		Dataset testData = new Dataset("resource/kernels/lllcomp/lllTestKernel");
		testData.addData(test);
		EvaluationProcedure eval = new EvaluationProcedure();
		String result = eval.SVMEvaluationForLLL(trainData, testData, svm, InteractionType.FALSE.ordinal(),
				InteractionType.REALSTRAIGHT.ordinal(), InteractionType.REALINVERSE.ordinal());
		PrintWriter writer = null;
		try {
			writer = new PrintWriter("resource/llltest");
			writer.append(result);
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public void cascadeSVMRunner4LLL(boolean recalcKernel) {
		CorpusFactory cFactory = new CorpusFactory();
		Text lll = cFactory.getCorpusFromPPIXML("resource/lll.xml", new SimplePreprocessor());
		lll.parse(null, "serialized", "resource/sparse/lll");

		Text llltest = cFactory.getCorpusFromPPIXML("resource/llltest.xml", new SimplePreprocessor());
		llltest.parse(null, "serialized", "resource/sparse/llltest");

		Collection<Interaction> train1 = lll.interactions();
		Collection<Interaction> test = llltest.interactions();

		// build precomputed kernels for 2 svm's
		PrecomputedKernel kernel = new PrecomputedKernel(train1, test, new CompositionKernel());
		kernel.suppressDirection = true;
		if (recalcKernel) {
			kernel.calculateTrainingMatrix();
			kernel.calculateTestMatrix();
			PrintWriter writer = null;
			try {
				writer = new PrintWriter("resource/kernels/lllcomp/lllTrainKernel1");
				kernel.printTrain(writer);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				writer.close();
			}
			try {
				writer = new PrintWriter("resource/kernels/lllcomp/lllTestKernel");
				kernel.printTest(writer);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				writer.close();
			}
		}
		LinkedList<Interaction> train2 = new LinkedList<Interaction>(train1);
		for (ListIterator<Interaction> i = train2.listIterator(); i.hasNext();) {
			if (i.next().status.equals(InteractionType.FALSE))
				i.remove();
		}
		kernel = new PrecomputedKernel(train2, test, new CompositionKernel());
		kernel.suppressDirection = false;
		if (recalcKernel) {
			PrintWriter writer = null;
			kernel.calculateTrainingMatrix();
			try {
				writer = new PrintWriter("resource/kernels/lllcomp/lllTrainKernel2");
				kernel.printTrain(writer);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				writer.close();
			}
		}

		SVM svm1 = new SVM();
		SVM svm2 = new SVM();
		try {
			svm1.setOptions(new String[] { "-K", "4", "-B", "1", "-C", "1", "-W0", "1", "-W1", "3" });
			svm2.setOptions(new String[] { "-K", "4", "-B", "1" });
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		Dataset trainData1 = new Dataset("resource/kernels/lllcomp/lllTrainKernel1");
		Dataset trainData2 = new Dataset("resource/kernels/lllcomp/lllTrainKernel2");
		Dataset testData1 = new Dataset("resource/kernels/lllcomp/lllTestKernel");
		testData1.addData(test);
		EvaluationProcedure eval = new EvaluationProcedure();
		eval.trainTestEvaluation(trainData1, testData1, svm1, InteractionType.FALSE.ordinal(), InteractionType.REAL
				.ordinal());
		Collection<Interaction> test2 = new ArrayList<Interaction>();
		List<String> prediction = eval.getPrediction();
		for (int i = 0, size = test.size(); i < size; i++) {
			String pred = prediction.get(i);
			if (Integer.parseInt(pred) == InteractionType.REAL.ordinal()) {
				test2.add(((List<Interaction>) test).get(i));
			}
		}
		kernel = new PrecomputedKernel(train2, test2, new CompositionKernel());
		kernel.suppressDirection = false;
		kernel.calculateTestMatrix();
		PrintWriter writer = null;
		try {
			writer = new PrintWriter("resource/kernels/lllcomp/lllTestKernel2");
			kernel.printTest(writer);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			writer.close();
		}
		Dataset testData2 = new Dataset("resource/kernels/lllcomp/lllTestKernel2");
		testData2.addData(test2);
		eval.clearPrediction();
		String result = eval.SVMEvaluationForLLL(trainData2, testData2, svm2, InteractionType.FALSE.ordinal(),
				InteractionType.REALSTRAIGHT.ordinal(), InteractionType.REALINVERSE.ordinal());
		try {
			writer = new PrintWriter("resource/llltestcascade");
			writer.append(result);
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public void SVMFoldsRunnerPrecomp(boolean recalcKernel) {
		int numFolds = 10;
		Dataset[] trainFolds = new Dataset[numFolds];
		Dataset[] testFolds = new Dataset[numFolds];
		for (int i = 0; i < numFolds; i++) {
			trainFolds[i] = new Dataset(pm.getParam("trainCVKernel") + i);
			trainFolds[i].addClassValues(readList(pm.getParam("trainCVClassValues") + i));
			testFolds[i] = new Dataset(pm.getParam("testCVKernel") + i);
			testFolds[i].addClassValues(readList(pm.getParam("testCVClassValues") + i));
		}
		SVM svm = new SVM();
		try {
			// "-C", "10", "-W0", "10", "-W1", "1"
			svm.setOptions(new String[] { "-K", "4", "-B", "1" });
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		EvaluationProcedure eval = new EvaluationProcedure();
		PerformanceMeasure pm = eval.crossValidation(svm, trainFolds, testFolds, InteractionType.FALSE.ordinal(),
				InteractionType.REALSTRAIGHT.ordinal(), InteractionType.REALINVERSE.ordinal(), InteractionType.REAL.ordinal());
		if (recalcKernel) {
			List<String> ids = new ArrayList<String>();
			try {
				BufferedReader reader = new BufferedReader(new FileReader(this.pm.getParam("ids")));
				String s;
				while ((s = reader.readLine()) != null) {
					ids.add(s);
				}
				PrintWriter writer = new PrintWriter(this.pm.getParam("prediction"));
				List<String> predictions = eval.getPrediction();
				for (int i = 0, size = ids.size(); i < size; i++) {
					writer.println(ids.get(i) + "\t" + predictions.get(i));
				}
				writer.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println(pm);
		System.out.println("Recall = " + pm.getRecall());
		System.out.println("Precision = " + pm.getPrecision());
		System.out.println("F-measure = " + pm.getFMeasure());
	}
	
	/*public void SVMFoldsRunner(boolean recalcKernel) {
		int numFolds = 10;
		Dataset[] trainFolds = new Dataset[numFolds];
		Dataset[] testFolds = new Dataset[numFolds];
		for (int i = 0; i < numFolds; i++) {
			trainFolds[i] = new Dataset(pm.getParam("trainCVFeatures") + i);
			trainFolds[i].addClassValues(readList(pm.getParam("trainCVFeatClassValues") + i));
			testFolds[i] = new Dataset(pm.getParam("testCVFeatures") + i);
			testFolds[i].addClassValues(readList(pm.getParam("testCVFeatClassValues") + i));
		}
		SVM svm = new SVM();
		try {
			// "-C", "10", "-W0", "10", "-W1", "1"
			svm.setOptions(new String[] { "-K", "2", "-B", "1" });
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		EvaluationProcedure eval = new EvaluationProcedure();
		PerformanceMeasure pm = eval.crossValidation(svm, trainFolds, testFolds, InteractionType.FALSE.ordinal(),
				InteractionType.REALSTRAIGHT.ordinal(), InteractionType.REALINVERSE.ordinal(), InteractionType.REAL.ordinal());
		if (recalcKernel) {
			List<String> ids = new ArrayList<String>();
			try {
				BufferedReader reader = new BufferedReader(new FileReader(this.pm.getParam("ids")));
				String s;
				while ((s = reader.readLine()) != null) {
					ids.add(s);
				}
				PrintWriter writer = new PrintWriter(this.pm.getParam("prediction"));
				List<String> predictions = eval.getPrediction();
				for (int i = 0, size = ids.size(); i < size; i++) {
					writer.println(ids.get(i) + "\t" + predictions.get(i));
				}
				writer.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println(pm);
		System.out.println("Recall = " + pm.getRecall());
		System.out.println("Precision = " + pm.getPrecision());
		System.out.println("F-measure = " + pm.getFMeasure());
	}*/


	private List<String> readList(String path) {
		BufferedReader reader;
		List<String> list = new ArrayList<String>();
		try {
			reader = new BufferedReader(new FileReader(path));
			String s;
			while ((s = reader.readLine()) != null) {
				list.add(s);
			}
			reader.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return list;
	}

	/*public void AIMedKernelBuilder(boolean doMain, boolean doFolds) {
		if (doMain) {
			CorpusFactory cFactory = new CorpusFactory();
			Text aimed = cFactory.getCorpusFromPPIXML("resource/aimed.xml", new DefaultPreprocessor());
			aimed.parse(null, "serialized", "resource/sparse/aimed");

			PrecomputedKernel kernel = new PrecomputedKernel(aimed.interactions(), new CompositionKernel());

			PrintWriter writer = null;

			try {
				writer = new PrintWriter("resource/kernels/AIMedcomp/aimedFullKernel");
				kernel.directPrintFullKernel(writer);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				writer.close();
			}
			try {
				writer = new PrintWriter("resource/kernels/AIMedcomp/aimedFullLabels");
				kernel.directPrintFullLabels(writer);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} finally {
				writer.close();
			}
		}
		if (doFolds) {
			PPIMapping m = new PPIMapping("AIMed");
			CorpusFactory cFactory = new CorpusFactory();
			Text aimed = cFactory.getCorpusFromPPIXML(pm.getParam("data"), new DefaultPreprocessor());
			aimed.parse(null, "serialized", pm.getParam("parse"));
			Map<String, List<Interaction>> map = new HashMap<String, List<Interaction>>();
			for (Interaction i : aimed.interactions()) {
				String[] split = i.id.split("\\.");
				String key = split[0] + "." + split[1] + ".";
				List<Interaction> list = map.get(key);
				if (list == null) {
					list = new ArrayList<Interaction>();
					map.put(key, list);
				}
				list.add(i);
			}

			File foldsDir = new File(pm.getParam("splits"));
			File[] trainFiles = foldsDir.listFiles(new FileFilter() {
				public boolean accept(File pathname) {
					return pathname.getName().contains("train");
				}
			});
			int fold = 0;
			try {
				PrintWriter writer3 = new PrintWriter(pm.getParam("ids"));
				for (File trainFile : trainFiles) {
					final String index = trainFile.getName().replace("train-", "");
					File testFile = foldsDir.listFiles(new FileFilter() {
						public boolean accept(File pathname) {
							return pathname.getName().contains(index);
						}
					})[0];

					List<String> train = new ArrayList<String>();
					List<String> test = new ArrayList<String>();
					try {
						BufferedReader reader = new BufferedReader(new FileReader(trainFile));
						String s;
						while ((s = reader.readLine()) != null)
							train.addAll(m.invMap(s));
						reader.close();
						reader = new BufferedReader(new FileReader(testFile));
						while ((s = reader.readLine()) != null)
							test.addAll(m.invMap(s));
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
					// Kernel<Interaction> k = new CompositionKernel();
					Kernel<Interaction> k = null;
					try {
						k = (Kernel<Interaction>) Class.forName(pm.getParam("kernelClass")).newInstance();
					} catch (InstantiationException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
					_log.debug("Writing train fold " + fold + "...");
					PrintWriter writer = new PrintWriter(pm.getParam("trainCVKernel") + fold);
					PrintWriter writer2 = new PrintWriter(pm.getParam("trainCVClassValues") + fold);
					int i = 0;
					for (String id1 : train) {
						_log.debug(id1);
						List<Interaction> i1List = map.get(id1);
						if (i1List == null)
							continue;
						for (Interaction i1 : i1List) {
							writer.print(i1.status.ordinal());
							writer2.println(i1.status.ordinal());
							writer.print("\t");
							writer.print("0:" + Integer.toString(i + 1));
							writer.print("\t");
							int j = 1;
							for (String id2 : train) {
								List<Interaction> i2List = map.get(id2);
								if (i2List == null)
									continue;
								for (Interaction i2 : i2List) {
									double kern = k.compute(i1, i2);
									writer.print(j++);
									writer.print(":");
									writer.print(kern);
									writer.print("\t");
								}
							}
							writer.println();
							i++;
						}
					}
					writer.close();
					writer2.close();
					_log.debug("Writing test fold " + fold + "...");
					writer = new PrintWriter(pm.getParam("testCVKernel") + fold);
					writer2 = new PrintWriter(pm.getParam("testCVClassValues") + fold);
					i = 0;
					for (String id1 : test) {
						_log.debug(id1);
						List<Interaction> i1List = map.get(id1);
						if (i1List == null)
							continue;
						for (Interaction i1 : i1List) {
							writer.print(i1.status.ordinal());
							writer2.println(i1.status.ordinal());
							writer3.println(i1.id);
							writer.print("\t");
							writer.print("0:" + Integer.toString(i + 1));
							writer.print("\t");
							int j = 1;
							for (String id2 : train) {
								List<Interaction> i2List = map.get(id2);
								if (i2List == null)
									continue;
								for (Interaction i2 : i2List) {
									double kern = k.compute(i1, i2);
									writer.print(j++);
									writer.print(":");
									writer.print(kern);
									writer.print("\t");
								}
							}
							writer.println();
							i++;
						}
					}
					writer.close();
					writer2.close();
					fold++;
				}
				writer3.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
	}*/

	//parallel - optional parameter, for parallel computation
	public void CVKernelBuilder(boolean suppressDirection, List<Integer> parallel) {
		CorpusFactory cFactory = new CorpusFactory();
		cFactory.suppressDirection = suppressDirection;
		Text corpus = cFactory.getCorpusFromPPIXML(pm.getParam("data"), new DefaultPreprocessor());
		corpus.parse(null, "serialized", pm.getParam("parse"));
		Collection<Interaction> full = corpus.interactions();
		Map<String, List<Interaction>> map = new HashMap<String, List<Interaction>>();
		//combine interactions per document in the map
		for (Interaction i : full) {
			String[] split = i.id.split("\\.");
			String key = split[0] + "." + split[1] + ".";
			List<Interaction> list = map.get(key);
			if (list == null) {
				list = new ArrayList<Interaction>();
				map.put(key, list);
			}
			list.add(i);
		}
		File foldsDir = new File(pm.getParam("splits"));
		File[] testFiles = foldsDir.listFiles();
		int numFolds = testFiles.length;
		ArrayList<String>[] folds = new ArrayList[numFolds];
		int i = 0;
		for (File testFile : testFiles) {
			ArrayList<String> fold = new ArrayList<String>();
			try {
				BufferedReader reader = new BufferedReader(new FileReader(testFile));
				String s;
				while ((s = reader.readLine()) != null)
					fold.add(s.concat("."));
				reader.close();
				folds[i] = fold;
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			i++;
		}
		try {
			PrintWriter writer3 = new PrintWriter(pm.getParam("ids"));
			for (int k = 0; k < numFolds; k++) {
				if(parallel.size()>0){
					if(!parallel.contains(k))
						continue;
				}
				Kernel<Interaction> kern = null;
				try {
					kern = (Kernel<Interaction>) Class.forName(pm.getParam("kernelClass")).newInstance();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
				PrintWriter writer = new PrintWriter(pm.getParam("trainCVKernel") + k);
				PrintWriter writer2 = new PrintWriter(pm.getParam("trainCVClassValues") + k);
				List<Interaction> test = new ArrayList<Interaction>(), train = new ArrayList<Interaction>();
				for (String doc : folds[k]) {
					if (map.get(doc) == null)
						_log.error("Document " + doc + " not found");
					else
						test.addAll(map.get(doc));
				}
				for (int j = 0; j < numFolds; j++) {
					if (k != j)
						for (String doc : folds[j])
							if (map.get(doc) == null)
								_log.error("Document " + doc + " not found");
							else
								train.addAll(map.get(doc));
				}
				i = 0;
				System.out.println("Writing train fold "+k);
				for (Interaction i1 : train) {
					System.out.println(i1.id);
					writer.print(i1.status.ordinal());
					writer2.println(i1.status.ordinal());
					writer.print("\t");
					writer.print("0:" + Integer.toString(i + 1));
					writer.print("\t");
					int j = 1;
					for (Interaction i2 : train) {
						writer.print(j++);
						writer.print(":");
						writer.print(kern.compute(i1, i2));
						writer.print("\t");
					}
					writer.println();
					i++;
				}
				writer.close();
				writer2.close();
				writer = new PrintWriter(pm.getParam("testCVKernel") + k);
				writer2 = new PrintWriter(pm.getParam("testCVClassValues") + k);
				i = 0;
				System.out.println("Writing test fold "+k);
				for (Interaction i1 : test) {
					System.out.println(i1.id);
					writer.print(i1.status.ordinal());
					writer2.println(i1.status.ordinal());
					writer3.println(i1.id);
					writer.print("\t");
					writer.print("0:" + Integer.toString(i + 1));
					writer.print("\t");
					int j = 1;
					for (Interaction i2 : train) {
						writer.print(j++);
						writer.print(":");
						writer.print(kern.compute(i1, i2));
						writer.print("\t");
					}
					writer.println();
					i++;
				}
				writer3.flush();
				writer.close();
				writer2.close();
			}
			writer3.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}


	/*public void SVMFoldsRunner4AIMed() {
		int numFolds = 10;
		SVM svm = new SVM();
		try {
			// "-C", "10", "-W0", "10", "-W1", "1"
			svm.setOptions(new String[] { "-K", "4", "-B", "1" });
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		Dataset[] train = new Dataset[numFolds];
		Dataset[] test = new Dataset[numFolds];
		for (int i = 0; i < numFolds; i++) {
			train[i] = new Dataset(pm.getParam("trainCVKernel") + i);
			train[i].addClassValues(readList(pm.getParam("trainCVClassValues") + i));
			test[i] = new Dataset(pm.getParam("testCVKernel") + i);
			test[i].addClassValues(readList(pm.getParam("testCVClassValues") + i));
		}

		EvaluationProcedure eval = new EvaluationProcedure();
		PerformanceMeasure pm = eval.crossValidation(svm, train, test, InteractionType.FALSE.ordinal(),
				InteractionType.REAL.ordinal());
		List<String> ids = eval.getPrediction();
		try {
			PrintWriter writer = new PrintWriter(this.pm.getParam("prediction"));
			List<String> predictions = eval.getPrediction();
			for (int i = 0, size = ids.size(); i < size; i++) {
				writer.println(ids.get(i) + "\t" + predictions.get(i));
			}
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		System.out.println(pm);
		System.out.println("Recall = " + pm.getRecall());
		System.out.println("Precision = " + pm.getPrecision());
		System.out.println("F-measure = " + pm.getFMeasure());
	}*/

	public void splitBuilder() {
		int numFolds = 10;
		int numDocs = 1100;
		for (int i = 0; i < numFolds; i++) {
			int num = i;
			try {
				PrintWriter writer = new PrintWriter("resource/splits/bioinfersplits/test" + Integer.toString(i + 1));
				while (num < numDocs) {
					writer.println("BioInfer.d" + num);
					num += 10;
				}
				writer.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
	}

	public void lengthAnalysis() {
		CorpusFactory cFactory = new CorpusFactory();
		Text corpus = cFactory.getCorpusFromPPIXML(pm.getParam("data"), new DefaultPreprocessor());
		corpus.parse(null, "serialized", pm.getParam("parse"));
		Collection<Interaction> full = corpus.interactions();
		Map<String, String> pred = new HashMap<String, String>();
		try {
			BufferedReader reader = new BufferedReader(new FileReader(pm.getParam("prediction")));
			String s;
			while ((s = reader.readLine()) != null) {
				String[] split = s.split("\\s+");
				pred.put(split[0], split[1]);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		Kernel<Interaction> kernel = new SyntacticKernel();
		PrintWriter writer = null;
		Map<Interaction, List<Double>> result = new HashMap<Interaction, List<Double>>();
		try {
			writer = new PrintWriter(pm.getParam("analysis"));
			for (Interaction i1 : full) {
				i1.predClass = pred.get(i1.id);
				// 'values' collects different length subtree matches
				List<Double> values = new ArrayList<Double>();
				values.add(0.0);
				for (Interaction i2 : full) {
					writer.print(i1.id + "\t" + i2.id + "\t");
					double kern = kernel.compute(i1, i2);
					writer.print(kern);
					String dist = ((SyntacticKernel) kernel).getDistribution();
					writer.println(dist);
					String[] split = dist.split("\t");
					values.set(0, values.get(0) + kern);
					for (String part : split) {
						if (part.equals(""))
							continue;
						String[] split2 = part.split("\\s");
						int length = Integer.parseInt(split2[0]);
						int amount = Integer.parseInt(split2[1]);
						for (int i = values.size(); i < length + 1; i++)
							values.add(0.0);
						values.set(length, values.get(length) + amount);
					}
				}
				result.put(i1, values);
			}
			writer.close();
			writer = new PrintWriter(pm.getParam("distribution"));
			NumberFormat nf = NumberFormat.getNumberInstance();
			nf.setMaximumFractionDigits(3);
			List<Interaction> keys = new ArrayList<Interaction>(result.keySet());
			Collections.sort(keys, new InteractionComparator());
			double[][] avg = new double[5][15];
			double[] len = new double[5];
			double[] kern = new double[5];
			double size = (double)keys.size();
			for (Interaction key : keys) {
				String type = key.getType();
				int i = 0;
				if (type.equals("TP"))
					i = 0;
				else if (type.equals("TN"))
					i = 1;
				else if (type.equals("FP"))
					i = 2;
				else if (type.equals("FN"))
					i = 3;
				else if (type.equals("WD"))
					i = 4;
				writer.print(type + " " + key.id + "\t");
				List<Double> values = result.get(key);
				avg[i][0]++;
				len[i] += key.depPath == null ? 0 : key.depPath.length;
				double divisor = values.get(0);
				kern[i] += divisor;
				for (int j = 1; j < values.size(); j++) {
					avg[i][j] += values.get(j) / size;
					writer.print(nf.format(values.get(j) / divisor) + "\t");
				}
				writer.println();
			}
			for (int i = 0; i < 5; i++) {
				switch (i) {
				case 0:
					writer.print("TP\t");
					break;
				case 1:
					writer.print("TN\t");
					break;
				case 2:
					writer.print("FP\t");
					break;
				case 3:
					writer.print("FN\t");
					break;
				case 4:
					writer.print("WD\t");
					break;
				}
				writer.print(avg[i][0] + "\t");
				writer.print(nf.format(kern[i] / avg[i][0] / size) + "\t");
				writer.print(nf.format(len[i] / avg[i][0]) + "\t");
				for (int j = 1; j < 15; j++) {
					writer.print(nf.format(avg[i][j] / avg[i][0]) + "\t");
				}
				writer.println();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			writer.close();
		}
	}

	public void featureVectorBuilder() {
		CorpusFactory cFactory = new CorpusFactory();
		Text corpus = cFactory.getCorpusFromPPIXML(pm.getParam("data"), new DefaultPreprocessor());
		corpus.parse(null, "serialized", pm.getParam("parse"));
		Collection<Interaction> full = corpus.interactions();
		Map<String, List<Interaction>> map = new HashMap<String, List<Interaction>>();
		for (Interaction i : full) {
			String[] split = i.id.split("\\.");
			String key = split[0] + "." + split[1] + ".";
			List<Interaction> list = map.get(key);
			if (list == null) {
				list = new ArrayList<Interaction>();
				map.put(key, list);
			}
			list.add(i);
		}

		File foldsDir = new File(pm.getParam("splits"));
		File[] testFiles = foldsDir.listFiles();
		int numFolds = testFiles.length;
		ArrayList<String>[] folds = new ArrayList[numFolds];
		int i = 0;
		for (File testFile : testFiles) {
			ArrayList<String> fold = new ArrayList<String>();
			try {
				BufferedReader reader = new BufferedReader(new FileReader(testFile));
				String s;
				while ((s = reader.readLine()) != null)
					fold.add(s.concat("."));
				reader.close();
				folds[i] = fold;
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			i++;
		}
		try {
			FeatureBuilder fb = new DepFeatureBuilder();
			for (int k = 0; k < numFolds; k++) {
				PrintWriter writer = new PrintWriter(pm.getParam("trainCVFeatures") + k);
				PrintWriter writer2 = new PrintWriter(pm.getParam("trainCVFeatClassValues") + k);
				List<Interaction> test = new ArrayList<Interaction>(), train = new ArrayList<Interaction>();
				for (String doc : folds[k]) {
					if (map.get(doc) == null)
						_log.error("Document " + doc + " not found");
					else
						test.addAll(map.get(doc));
				}
				for (int j = 0; j < numFolds; j++) {
					if (k != j)
						for (String doc : folds[j])
							if (map.get(doc) == null)
								_log.error("Document " + doc + " not found");
							else
								train.addAll(map.get(doc));
				}
				i = 1;
				for (Interaction i1 : train) {
					double[] v = fb.getFeatureVector(i1).toDoubleArray();
					writer.print(i1.status.ordinal());
					writer2.println(i1.status.ordinal());
					writer.print("\t");
					writer.print("0:" + Integer.toString(i));
					for (int j = 0, size = v.length; j<size; j++) {
						writer.print("\t");
						writer.print(j+1);
						writer.print(":");
						writer.print(v[j]);
					}
					writer.print("\n");
					i++;
				}
				writer.close();
				writer2.close();
				writer = new PrintWriter(pm.getParam("testCVFeatures") + k);
				writer2 = new PrintWriter(pm.getParam("testCVFeatClassValues") + k);
				i = 1;
				for (Interaction i1 : test) {
					double[] v = fb.getFeatureVector(i1).toDoubleArray();
					writer.print(i1.status.ordinal());
					writer2.println(i1.status.ordinal());
					writer.print("\t");
					writer.print("0:" + Integer.toString(i));
					writer.print("\t");
					for (int j = 0, size = v.length; j<size; j++) {
						writer.print("\t");
						writer.print(j+1);
						writer.print(":");
						writer.print(v[j]);
					}
					writer.print("\n");
					i++;
				}
				writer.close();
				writer2.close();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

	}
	
	public void contentAnalysis(boolean directed){
		CorpusFactory cFactory = new CorpusFactory();
		Text corpus = cFactory.getCorpusFromPPIXML(pm.getParam("data"), new DefaultPreprocessor());
		corpus.parse(null, "serialized", pm.getParam("parse"));
		Collection<Interaction> full = corpus.interactions();
		int numClasses = directed?5:3;
		Map<String, Integer>[] comps = new HashMap[numClasses];
		double[] amount = new double[numClasses];
		double[] length = new double[numClasses];	//for counting average length
		//for counting median length
		List<Integer>[] length2 = new ArrayList[numClasses];
		try {
			PrintWriter writer = new PrintWriter(pm.getParam("contentStat"));
			for(Interaction i : full){
				if(i.depPath == null)
					continue;
				int index = i.status.ordinal();
				if(!directed && index > 2)
					index = 0;
				Map<String, Integer> map = comps[index];
				amount[index]++;
				length[index] += i.depPath.length;
				if(length2[index] == null)
					length2[index] = new ArrayList<Integer>();
				length2[index].add(i.depPath.length);
				if(map == null){
					map = new HashMap<String, Integer>();
					comps[index] = map;
				}
				for(Edge e : i.depPath.edges){
					String key = (String)e.getUserDatum(Keys.LABEL);
					Integer count = map.get(key);
					if(count == null)
						count = new Integer(0);
					map.put(key, count+1);
				}
			}
			NumberFormat nf = NumberFormat.getInstance();
			nf.setMaximumFractionDigits(3);
			for(int i = 0; i<comps.length; i++){
				if(comps[i] == null){
					continue;
				}
				Collections.sort(length2[i]);
				writer.println(InteractionType.values()[i].toString()+"\t Avg len: "+length[i]/amount[i]+"Med len: "+length2[i].get(length2[i].size()/2));
				for(String key : comps[i].keySet()){
					writer.println(key+"\t"+nf.format(comps[i].get(key)/amount[i]));
				}
			}
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}		
	}

	public void nestedProteinsInfo() {
		CorpusFactory cFactory = new CorpusFactory();
		Text lll = cFactory.getCorpusFromPPIXML("resource/bioinfer.xml", new SimplePreprocessor());
	}
	
	public void calculateROC(){
		List<String> list = readList(pm.getParam("prediction"));
		List<String> result = new ArrayList<String>();
		for(String s : list){
			String[] split = s.split("\t");
			//temporary hack
			/*if(split[3].equals("1"))
				split[3] = "0";
			else
				split[3] = "1";
			*/
			split[1] = Double.toString(1-Double.parseDouble(split[1]));
			result.add(split[1]+"\t"+split[3]);
		}
		Collections.sort(result, new ProbablitiesComparator());
		try {
			PrintWriter writer = new PrintWriter(pm.getParam("rocSource"));
			for(String s : result){
				writer.append(s+"\n");
			}
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		AUCCalculator auc = new AUCCalculator();
		auc.main(new String[]{pm.getParam("rocSource"), "list"});
	}
	
	public void crossDatasetKernel(boolean doTrain, boolean doTest){
		String[] trainSets = pm.getParam("trainSet").split(";");
		PropertyManager _pm = new PropertyManager();
		CorpusFactory cFactory = new CorpusFactory();
		cFactory.suppressDirection = true;
		Collection<Interaction> train = new ArrayList<Interaction>();
		Collection<Interaction> test = new ArrayList<Interaction>();
		for(String prop : trainSets){
			_pm.readParam(prop);
			Text corpus = cFactory.getCorpusFromPPIXML(_pm.getParam("data"), new DefaultPreprocessor());
			corpus.parse(null, "serialized", _pm.getParam("parse"));
			train.addAll(corpus.interactions());
		}
		_pm.readParam(pm.getParam("testSet"));
		Text corpus = cFactory.getCorpusFromPPIXML(_pm.getParam("data"), new DefaultPreprocessor());
		corpus.parse(null, "serialized", _pm.getParam("parse"));
		test.addAll(corpus.interactions());
		
		Kernel<Interaction> kern = null;
		try {
			kern = (Kernel<Interaction>) Class.forName(pm.getParam("kernelClass")).newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		PrintWriter writer3 = null;
		PrintWriter writer2 = null;
		PrintWriter writer = null;
		try {
			writer = new PrintWriter(pm.getParam("trainKernel"));
			writer3 = new PrintWriter(pm.getParam("ids"));
			writer2 = new PrintWriter(pm.getParam("trainClassValues"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}		
		int i = 1;
		if(doTrain){
			System.out.println("Writing training kernel");
			for (Interaction i1 : train) {
				System.out.println(i1.id);
				writer.print(i1.status.ordinal());
				writer2.println(i1.status.ordinal());
				writer.print("\t");
				writer.print("0:" + Integer.toString(i++));
				writer.print("\t");
				int j = 1;
				for (Interaction i2 : train) {
					writer.print(j++);
					writer.print(":");
					writer.print(kern.compute(i1, i2));
					writer.print("\t");
				}
				writer.println();
			}
		}
		writer.close();
		try {
			writer = new PrintWriter(pm.getParam("testKernel"));
			writer2 = new PrintWriter(pm.getParam("testClassValues"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		i = 1;
		if(doTest){
			System.out.println("Writing test kernel");
			for (Interaction i1 : test) {
				System.out.println(i1.id);
				writer.print(i1.status.ordinal());
				writer2.println(i1.status.ordinal());
				writer3.println(i1.id);
				writer.print("\t");
				writer.print("0:" + Integer.toString(i++));
				writer.print("\t");
				int j = 1;
				for (Interaction i2 : train) {
					writer.print(j++);
					writer.print(":");
					writer.print(kern.compute(i1, i2));
					writer.print("\t");
				}
				writer.println();
			}
		}
		writer.close();
		writer3.close();
	}
	
	private void refreshIds(){
		
	}
	
	//needed one time
	/*private void convertAIMedFolds(){
		PPIMapping m = new PPIMapping("AIMed");
		File foldsDir = new File(pm.getParam("splits"));
		File[] testFiles = foldsDir.listFiles(new FileFilter() {
			public boolean accept(File pathname) {
				return pathname.getName().contains("test");
			}
		});
		int i = 0;
		for(File file : testFiles){
			try {
				PrintWriter writer = new PrintWriter(pm.getParam("splits")+File.separator+"test"+i);
				try {
					BufferedReader reader = new BufferedReader(new FileReader(file));
					String s;
					while((s = reader.readLine())!=null){
						if(!s.equals("")){
							List<String> list = m.invMap(s);
							for(String id : list){
								writer.println(id.substring(0,id.length()-1));
							}
						}
					}
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}				
				writer.close();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
			i++;
		}
	}*/

	/*
	 * args:
	 * 	0 - header : "**************LLL SYNTACTIC KERNEL*****************"
	 * 	1 - outFile: system.out
	 * 	2 - propFile: props/bioinfercomp.properties
	 *  3 - doKernels
	 *  4 - runSVM
	 *  5 - doLengthAnalysis
	 *  6 - parallel : 1 2 3
	 */
	public static void main(String[] args) {
		if(args.length == 3){
			_Runners r = new _Runners(args[0]);
			r.crossDatasetKernel(Boolean.parseBoolean(args[1]), Boolean.parseBoolean(args[2]));
			return;
		}
		if(args.length<7){
			System.out.println("args:\n"+
					"* 	0 - header  : **************LLL SYNTACTIC KERNEL*****************\n"+
					 "* 1 - outFile : system.out\n"+
					 "* 2 - propFile: props/bioinfercomp.properties\n"+
					 "* 3 - doKernels\n"+
					 "* 4 - runSVM\n"+
					 "* 5 - doLengthAnalysis\n" +
					 "* 6 - calculate ROC\n" +
					 "* 7 - parallel : 1 2 3 opt");
			return;
		}
		String header = args[0];
		String outFile = args[1];
		String propFile = args[2];
		boolean doKernels = Boolean.parseBoolean(args[3]);
		boolean runSVM = Boolean.parseBoolean(args[4]);
		boolean doLengthAnalysis = Boolean.parseBoolean(args[5]);
		boolean calcROC = Boolean.parseBoolean(args[6]);
		List<Integer> parallel = new ArrayList<Integer>();
		if(args.length>7){
			int i = 7;
			while(i<args.length)
				parallel.add(Integer.parseInt(args[i++]));
		}
		PrintStream out = null;
		try {
			String userDir = System.getProperty("user.dir");
			File file = new File(userDir, outFile);
			out = new PrintStream(file);
			System.setOut(out);
			System.out.println(header);
			_Runners r = new _Runners(propFile);
			if(doKernels){
				String suppressDirection = r.pm.getParam("suppressDirection");
				boolean sup = false;
				if(suppressDirection !=null)
					sup = Boolean.parseBoolean(suppressDirection);
				//if(propFile.contains("AIMed")||propFile.contains("aimed"))
				//	r.AIMedKernelBuilder(false, true);
				//else
					r.CVKernelBuilder(sup, parallel);
			}
			if(runSVM){
				//if(propFile.contains("AIMed"))
				//	r.SVMFoldsRunner4AIMed();
				//else
					r.SVMFoldsRunnerPrecomp(true);
			}				
			if(doLengthAnalysis)
				r.lengthAnalysis();
			if(calcROC)
				r.calculateROC();
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return;
		}finally{
			if(out!=null){
				out.close();
			}
		}
	}

	class InteractionComparator implements Comparator<Interaction> {

		public int compare(Interaction o1, Interaction o2) {
			return o1.getType().compareTo(o2.getType());
		}

	}
	
	class ProbablitiesComparator implements Comparator<String> {

		public int compare(String o1, String o2) {
			double p1 = Double.parseDouble(o1.split("\t")[0]);
			double p2 = Double.parseDouble(o2.split("\t")[0]);
			if(p1==p2)
				return 0;
			if(p1<p2)
				return 1;
			return -1;
		}

	}
}
